# https://blog.csdn.net/weixin_42326479/article/details/102938733
import cv2
# import matplotlib.pyplot as plt
import numpy as np


# import math
# import time
# import os

# Canny边缘检测
def CannyThreshold(lowThreshold):
    detected_edges = cv2.GaussianBlur(grayImage, (3, 3), 0)
    detected_edges = cv2.Canny(detected_edges,
                               lowThreshold,
                               lowThreshold * ratio,
                               apertureSize=kernel_size)
    dst = cv2.bitwise_and(img_counter, img_counter, mask=detected_edges)
    #cv2.namedWindow('canny', cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO)
    cv2.imshow('canny', dst)

# 轮廓参数设置
def FindCountour(preimg):
    contours, hierarchy = cv2.findContours(preimg.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
    contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10]
    return contours

def ContoursDraw(min_):
    cv2.drawContours(img_counter, contoursC[min_], -1, (0, 0, 255), 3)
    cv2.imshow('CannyDrawContours', img_counter)


img = cv2.imread(r"D:\data\CUGW-test\20230819left2\tmp\0_0.JPG")
img_counter = img.copy()
img_transform = img.copy()
grayImage = cv2.cvtColor(img_counter, cv2.COLOR_BGR2GRAY)

lowThreshold = 0
max_lowThreshold = 400
ratio = 3
kernel_size = 3
cv2.namedWindow('canny detection', cv2.WINDOW_KEEPRATIO)
cv2.createTrackbar('min', 'canny detection', lowThreshold, max_lowThreshold, CannyThreshold)
CannyThreshold(0)
if cv2.waitKey(0) == 27:
    cv2.destroyAllWindows()
# 更改参数
canny_value = eval(input("在Canny边缘检测的参数中选择轮廓最清晰的参数："))  #命令行中输入52
gaussImage = cv2.GaussianBlur(grayImage, (3, 3), 0)
C = cv2.Canny(gaussImage, canny_value, canny_value * 3)
cv2.imwrite(r"imgs_out\Canny.jpg", C)

contoursC = FindCountour(C)

cv2.namedWindow('CannyDrawContours', cv2.WINDOW_KEEPRATIO)
min_ = 0
cv2.createTrackbar('number', 'CannyDrawContours', min_, len(contoursC), ContoursDraw)
ContoursDraw(0)
if cv2.waitKey(0) == 27:
    cv2.destroyAllWindows()
n = eval(input("请输入最适合的轮廓："))   #没有合适的值，自动校正不可行

pentagram = contoursC[n]
cv2.drawContours(img_counter, pentagram, -1, (0, 0, 255), 3)
# cv2.imwrite(r"E:\result_data\jingjiang\ex-first\diban_counter\counter.jpg", img_counter)
cv2.imshow("img_counter", img_counter)

# # 找四边形的四个关键点#######################################################################################################
P1 = np.array(pentagram[:, 0][pentagram[:, :, 0].argmin()])  # 左上
P2 = np.array(pentagram[:, 0][pentagram[:, :, 1].argmin()])  # 右上
P3 = np.array(pentagram[:, 0][pentagram[:, :, 1].argmax()])  # 左下
P4 = np.array(pentagram[:, 0][pentagram[:, :, 0].argmax()])  # 右下

cv2.circle(img_transform, tuple(P1), 2, (255, 0, 255), 5)
cv2.circle(img_transform, tuple(P2), 2, (255, 0, 255), 5)
cv2.circle(img_transform, tuple(P3), 2, (255, 0, 255), 5)
cv2.circle(img_transform, tuple(P4), 2, (255, 0, 255), 5)
# cv2.imshow("img_point", img_transform)
# cv2.imwrite(r"E:\result_data\jingjiang\ex-first\diban_counter\point.jpg", img_transform)
#
# # 透视变换#################################################################################################################
# # 输入梯形的四个顶点
srcPoints = np.vstack((P1, P2, P3, P4))
srcPoints = np.float32(srcPoints)
# 目标的像素值大小
long = 550  # 72为分辨率,30及21是目标的实际尺寸，可用户输入.2.54为英寸的换算
short = 550
# 设置目标画布的大小
canvasPoints = np.array([[0, 0], [int(long), 0], [0, int(short)], [int(long), int(short)]])
canvasPoints = np.float32(canvasPoints)
# 计算转换矩阵
perspectiveMatrix = cv2.getPerspectiveTransform(srcPoints, canvasPoints)  # srcPoints是校正前的四个角点坐标，canvasPoints是校正后的四个角点坐标
# 完成透视变换
perspectiveImg = cv2.warpPerspective(img_transform, perspectiveMatrix,
                                     (int(long), int(short)))  # img_transform是原始图片，(int(long), int(short))画布尺寸
print("开始校正")
cv2.namedWindow("perspectiveImg", cv2.WINDOW_FREERATIO)
cv2.imshow("perspectiveImg", perspectiveImg)
# cv2.imwrite(r"E:\result_data\jingjiang\ex-first\diban_counter\transform.jpg", perspectiveImg)
cv2.waitKey(0)
